home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Languages Suite
/
ProgramD2.iso
/
Borland
/
Borland C++ V5.02
/
CLASSSRC.PAK
/
USTRING.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-06
|
11KB
|
531 lines
//----------------------------------------------------------------------------
// Copyright (c) 1994, 1997 by Borland International, All Rights Reserved
//
//$Revision: 5.8 $
//
// TString (& TUString) implementation (others functions are inline)
//----------------------------------------------------------------------------
#include <winsys/pch.h>
#include <winsys/string.h>
#include <services/memory.h>
#include <string.h>
#include <tchar.h>
TUString TUString::Null; // null TAutoStrings reference this object
#if defined(BI_HAS_WCHAR)
//
// Take a wide char string & return an ANSI string in a new'd char[] buffer
//
char* TUString::ConvertWtoA(const wchar_t* src, size_t len)
{
size_t size = WideCharToMultiByte(CP_ACP, 0, src, len, 0, 0, 0, 0);
char* dst = new char[size + (len != -1)]; // room for null if fixed size
size = WideCharToMultiByte(CP_ACP, 0, src, len, dst, size, 0, 0);
if (len != -1)
dst[size] = 0;
return dst;
}
//
// Take an ANSI char string & return a wide string in a new'd wchar_t[] buffer
//
wchar_t* TUString::ConvertAtoW(const char* src, size_t len)
{
size_t size = MultiByteToWideChar(CP_ACP, 0, src, len, 0, 0);
wchar_t* dst = new wchar_t[size + (len != -1)];
size = MultiByteToWideChar(CP_ACP, 0, src, len, dst, size);
if (len != -1)
dst[size] = 0;
return dst;
}
#endif
//------------------------------------------------------------------------
//
// Change UString to isCopy regardless of current type
//
_TCHAR* TUString::ChangeToCopy()
{
_TCHAR* dst = 0;
const _TCHAR far* src;
int len;
switch (Kind) {
case isNull:
return 0;
case isConst:
src = Const;
len = _tcslen(Const);
break;
case isCopy:
return Copy;
#if defined(BI_HAS_WCHAR)
case isWConst:
dst = ConvertWtoA(WConst);
break;
case isWCopy:
dst = ConvertWtoA(WCopy);
delete[] WCopy;
break;
#endif
#if defined(BI_OLECHAR_WIDE)
case isBstr:
case isExtBstr:
dst = ConvertWtoA(Bstr, ::SysStringLen(Bstr));
break;
#else
case isBstr:
case isExtBstr:
src = Bstr;
len = ::SysStringLen(Bstr);
break;
#endif
case isString:
src = ((string*)&String)->c_str();
len = ((string*)&String)->length();
}
if (!dst) {
dst = new _TCHAR[len+1];
memcpy(dst, src, len+1);
}
if (Kind == isBstr)
::SysFreeString(Bstr);
Kind = isCopy;
Copy = dst;
return Copy;
}
#if defined(BI_HAS_WCHAR)
//
// Change UString to isWCopy regardless of current type
//
wchar_t* TUString::ChangeToWCopy()
{
wchar_t* dst = 0;
const wchar_t* src;
int len;
switch (Kind) {
case isNull:
return 0;
case isConst:
dst = ConvertAtoW(Const);
break;
case isCopy:
dst = ConvertAtoW(Copy);
delete[] Copy;
break;
case isWConst:
src = WConst;
len = _tcslen(WConst);
break;
case isWCopy:
return WCopy;
#if defined(BI_OLECHAR_WIDE)
case isBstr:
case isExtBstr:
src = Bstr;
len = ::SysStringLen(Bstr);
break;
#else // This case probably never happens
case isBstr:
case isExtBstr:
dst = ConvertAtoW(Bstr, ::SysStringLen(Bstr));
break;
#endif
case isString:
dst = ConvertAtoW(((string*)&String)->c_str(), ((string*)&String)->length());
}
if (!dst) {
dst = new wchar_t[len+1];
memcpy(dst, src, (len+1) * sizeof(wchar_t));
}
if (Kind == isBstr)
::SysFreeString(Bstr);
Kind = isWCopy;
WCopy = dst;
return WCopy;
}
#endif
//------------------------------------------------------------------------
// inline ctors used by Create functions.
// Note: these are never made public or exported from this unit
//
//
inline TUString::TUString(const _TCHAR far& str)
:
Kind(isConst),
Const(&str),
RefCnt(1),
Lang(0)
{
}
//
inline TUString::TUString(_TCHAR& str)
:
Kind(isCopy), RefCnt(1), Lang(0)
{
Copy = new _TCHAR[_tcslen(&str)+1];
_tcscpy(Copy, &str);
}
#if defined(BI_HAS_WCHAR)
//
inline TUString::TUString(const wchar_t& str)
:
Kind(isWConst),
WConst(&str),
RefCnt(1),
Lang(0)
{
}
//
inline TUString::TUString(wchar_t& str)
:
Kind(isWCopy),
RefCnt(1),
Lang(0)
{
WCopy = new wchar_t[_tcslen(&str)+1];
_tcscpy(WCopy, &str);
}
#endif
//
inline TUString::TUString(BSTR str, bool loan, TLangId lang)
:
Kind(loan ? isExtBstr : isBstr),
Bstr(str),
RefCnt(int16(loan ? 2 : 1)),
Lang(lang)
{
}
//
inline TUString::TUString(TSysStr& str, bool loan, TLangId lang)
:
Kind(loan ? isExtBstr : isBstr),
Bstr(str.operator BSTR()),
RefCnt(int16(loan ? 2 : 1)),
Lang(lang)
{
}
//
inline void* operator new(size_t, TStringRef** p) {return p;}
//
inline TUString::TUString(const string& str)
:
Kind(isString), RefCnt(1), Lang(0)
{
new(&String) string(str);
}
//------------------------------------------------------------------------
// Static creation, or factory functions return pointers to new UStrings, or
// pointers to the Null UString
//
//
TUString* TUString::Create(const _TCHAR far* str)
{
return str /*&& *str*/ ? new TUString(*str) : &++Null;
}
//
TUString* TUString::Create(_TCHAR* str)
{
return str /*&& *str*/ ? new TUString(*str) : &++Null;
}
#if defined(BI_HAS_WCHAR)
//
TUString* TUString::Create(const wchar_t* str)
{
return str /*&& *str*/ ? new TUString(*str) : &++Null;
}
//
TUString* TUString::Create(wchar_t* str)
{
return str /*&& *str*/ ? new TUString(*str) : &++Null;
}
#endif
//
TUString* TUString::Create(BSTR str, bool loan, TLangId lang)
{
if (str && ::SysStringLen(str))
return new TUString(str, loan, lang);
if (!loan)
::SysFreeString(str);
return &++Null;
}
//
TUString* TUString::Create(TSysStr& str, bool loan, TLangId lang)
{
return Create(str.operator BSTR(), loan, lang);
}
//
TUString* TUString::Create(const string& str)
{
return str.length() ? new TUString(str) : &++Null;
}
//------------------------------------------------------------------------
//
//
//
TUString* TUString::Assign(const TUString& s)
{
if (RefCnt == 1 && Kind != isNull && Kind != isExtBstr)
Free();
else
--*this;
CONST_CAST(TUString&,s).RefCnt++;
return &CONST_CAST(TUString&,s);
}
//
TUString* TUString::Assign(const string& s)
{
if (s.length() && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isString;
new(&String) string(s);
return this;
}
else {
--*this;
return Create(s);
}
}
//
TUString* TUString::Assign(const _TCHAR far* s)
{
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isConst;
Const = s;
return this;
}
else {
--*this;
return Create(s);
}
}
//
TUString* TUString::Assign(_TCHAR* s)
{
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isCopy;
Copy = new _TCHAR[_tcslen(s)+1];
_tcscpy(Copy, s);
return this;
}
else {
--*this;
return Create(s);
}
}
#if defined(BI_HAS_WCHAR)
//
TUString* TUString::Assign(const wchar_t* s)
{
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isWConst;
WConst = s;
return this;
}
else {
--*this;
return Create(s);
}
}
//
TUString* TUString::Assign(wchar_t* s)
{
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isWCopy;
WCopy = new wchar_t[_tcslen(s)+1];
_tcscpy(WCopy, s);
return this;
}
else {
--*this;
return Create(s);
}
}
#endif
//
TUString* TUString::Assign(BSTR str, TLangId lang)
{
if (RefCnt==1 && Kind != isNull && Kind != isExtBstr) {
Free();
Kind = isBstr;
Bstr = str;
Lang = lang;
if (Bstr && ::SysStringLen(Bstr))
return this;
delete this;
return &++Null;
}
else {
--*this;
return Create(str, false, lang);
}
}
//------------------------------------------------------------------------
//
TUString::operator const _TCHAR far*() const
{
switch (Kind) {
case isNull: return 0;
case isConst: return Const;
case isCopy: return Copy;
case isString: return ((string*)&String)->c_str();
#if defined(BI_OLECHAR_WIDE)
case isBstr:
case isExtBstr: return CONST_CAST(TUString*,this)->ChangeToCopy();
#else
case isBstr:
case isExtBstr: return Bstr;
#endif
case isWConst:
case isWCopy: return CONST_CAST(TUString*,this)->ChangeToCopy();
}
return 0; // suppress warning
}
//
TUString::operator _TCHAR*()
{
return ChangeToCopy();
}
#if defined(BI_HAS_WCHAR)
//
TUString::operator const wchar_t*() const
{
switch (Kind) {
case isNull: return 0;
case isWConst: return WConst;
case isWCopy: return WCopy;
#if defined(BI_OLECHAR_WIDE)
case isBstr:
case isExtBstr: return Bstr;
#else
case isBstr:
case isExtBstr: return CONST_CAST(TUString*,this)->ChangeToWCopy();
#endif
case isConst:
case isCopy:
case isString: return CONST_CAST(TUString*,this)->ChangeToWCopy();
}
return 0; // suppress warning
}
//
TUString::operator wchar_t*()
{
return ChangeToWCopy();
}
#endif
//------------------------------------------------------------------------
//
//
//
int TUString::Length() const
{
switch (Kind) {
case isNull: return 0;
#if defined(BI_HAS_WCHAR)
case isWConst: return _tcslen(WConst);
case isWCopy: return _tcslen(WCopy);
#endif
case isBstr:
case isExtBstr: return ::SysStringLen(Bstr);
case isConst: return _tcslen(Const);
case isCopy: return _tcslen(Copy);
case isString: return ((string*)&String)->length();
}
return 0; // suppress warning
}
//------------------------------------------------------------------------
//
// Revoke BSTR ownership from this UString, i.e. make this UString relinquish
//
void TUString::RevokeBstr(BSTR s)
{
if (Kind != isExtBstr || Bstr != s) // Don't have it anymore
return;
if (RefCnt == 1) { // We go away. Assume that our envelope knows about this!
Kind = isNull;
delete this;
return;
}
#if defined(BI_OLECHAR_WIDE)
ChangeToWCopy(); // Make an appropriate copy of it
#else
ChangeToCopy();
#endif
}
//
// Pass BSTR ownership to this UString
//
void TUString::ReleaseBstr(BSTR s)
{
if (Kind == isExtBstr && Bstr == s) {
Kind = isBstr;
--*this;
}
else // Has been overwritten with converted type, don't need anymore
::SysFreeString(s);
}
//
// Free any resources held by this UString. Union & Kind left in random state;
// must be reinitialized before use.
//
void TUString::Free()
{
switch (Kind) {
case isCopy: delete[] Copy; break;
#if defined(BI_HAS_WCHAR)
case isWCopy: delete[] WCopy; break;
#endif
case isBstr: ::SysFreeString(Bstr); break;
case isString: ((string*)&String)->string::~string();
}
Lang = 0;
//Kind = isNull; // for safety, not really needed
}